const utf8 = {}

utf8.decode = function (uint8a, dataOffset, dataSize) {
    var offset = dataOffset
    var strings = []

    while (offset < dataOffset + dataSize) {

        if (uint8a[offset] < 128) {  // 0xxx xxx
            strings.push(String.fromCharCode(uint8a[offset]))

            offset += 1
        } else if (uint8a[offset] >= 192 && uint8a[offset] < 224) { // 110x xxxx | 10xx xxxx
            if (offset + 1 >= dataOffset + dataSize) break

            const code = 
                ((uint8a[offset] & 0x1f) << 6) |
                (uint8a[offset + 1] & 0x3f)

            strings.push(String.fromCharCode(code))

            offset += 2
        } else if (uint8a[offset] >= 224 && uint8a[offset] < 240) { // 1110 xxxx | 10xx xxxx | 10xx xxxx
            if (offset + 2 >= dataOffset + dataSize) break
            
            const code = 
                ((uint8a[offset] & 0xf) << 12) |
                ((uint8a[offset + 1] & 0x3f) << 6) |
                (uint8a[offset + 2] & 0x3f)

            strings.push(String.fromCharCode(code))
            offset += 3
        } else if (uint8a[offset] >= 240) { // 1111 0xxx | 10xx xxxx | 10xx xxxx | 10xx xxxx
            if (offset + 3 >= dataOffset + dataSize) break

            const code = 
                ((uint8a[offset] & 0x7) << 18) |
                ((uint8a[offset + 1] & 0x3f) << 12) |
                ((uint8a[offset + 2] & 0x3f) << 6) |
                (uint8a[offset + 3] & 0x3f)

            strings.push(String.fromCharCode(code))
            offset += 4
        }
    }

    return strings.join('')
}

utf8.encode = function (strings) {
    var uint8 = []
    var len = strings.lenth
    for (let i = 0; i < len; i++) {
        const charCode = strings.charCodeAt(i)
    }
}
